package com.jshan.blog.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jshan.blog.annotation.OperationLog;
import com.jshan.blog.base.admin.dto.ChangePwdDto;
import com.jshan.blog.base.admin.dto.LoginAndRegisterDto;
import com.jshan.blog.base.admin.entity.SysUser;
import com.jshan.blog.constans.RedisCodeConst;
import com.jshan.blog.enums.BizCodeEnums;
import com.jshan.blog.result.Result;
import com.jshan.blog.service.SysUserService;
import com.jshan.blog.utils.BcyEncodingUtil;
import com.jshan.blog.utils.RandomCode;
import com.jshan.blog.utils.RedisUtil;
import com.jshan.blog.valid.AddGroupValid;
import com.jshan.blog.valid.LoginAndRegisterGroupValid;
import com.jshan.blog.valid.UpdateGroupValid;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/user")
@Tag(name = "用户相关操作")
public class UserController {

    @Resource
    private SysUserService userService;

    @Resource
    private RedisUtil redisUtil;

    /**
     * 注册接口
     *
     * @param loginAndRegisterDto 注册使用的 dto
     * @return 返回结果
     */
    // @OperationLog(value = "注册", operationType = "新增")
    @Operation(summary = "注册")
    @PostMapping("/register")
    public Result register(@Validated(value = {UpdateGroupValid.class})
                           @RequestBody LoginAndRegisterDto loginAndRegisterDto) {
        log.info("注册信息:{}", loginAndRegisterDto);
        String code = getStrCode();
        if (ObjectUtils.isEmpty(code)) {
            return Result.fail(BizCodeEnums.FAILE.getCode(), "验证码已过期！");
        }
        if (!code.equals(loginAndRegisterDto.getCode())) {
            return Result.fail(BizCodeEnums.FAILE.getCode(), "验证码不正确，请重新输入！");
        }
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        SysUser user = userService.getOne(wrapper.eq(SysUser::getUsername, loginAndRegisterDto.getUsername()));
        if (ObjectUtils.isNotEmpty(user)) {
            log.error("用户已存在，请重新注册");
            return Result.fail(BizCodeEnums.FAILE.getCode(), "用户已存在，请重新注册");
        }
        Boolean flag = userService.saveDto(loginAndRegisterDto);
        if (flag) {
            return Result.ok(BizCodeEnums.SUCCESS.getCode(), "注册成功");
        }
        return Result.fail(BizCodeEnums.FAILE.getCode(), "注册失败");
    }

    @OperationLog(value = "修改密码", operationType = "修改")
    @Operation(summary = "修改密码")
    @PutMapping("/changePwd")
    public Result changePwd(@Validated(value = {UpdateGroupValid.class})
                            @RequestBody ChangePwdDto changePwdDto) {
        if (StpUtil.getLoginIdAsInt() != changePwdDto.getId()){
            return Result.fail(BizCodeEnums.FAILE.getCode(), "只能修改当前登录用户的密码");
        }
        if (changePwdDto.getNewPwd().equals(changePwdDto.getOldPwd())) {
            return Result.fail(BizCodeEnums.FAILE.getCode(), "新旧密码不能一致");
        }
        SysUser userInfo = userService.getById(changePwdDto.getId());
        Boolean flag = BcyEncodingUtil.checkPwd(changePwdDto.getOldPwd(), userInfo.getPwd());
        // if (changePwdDto.getNewPwd().equals(changePwdDto.getOldPwd())){
        //     return Result.fail(BizCodeEnums.FAILE.getCode(),"两次密码不能相同");
        // }
        if (flag) {
            userInfo.setPwd(BcyEncodingUtil.bcyEncode(changePwdDto.getNewPwd()));
            userInfo.setUpdateTime(LocalDateTime.now());
            userInfo.setLastLoginTime(LocalDateTime.now());
            if (userService.updateById(userInfo)) {
                return Result.ok(BizCodeEnums.SUCCESS.getCode(), "密码修改成功");
            }
        }
        return Result.fail(BizCodeEnums.FAILE.getCode(), "密码不正确");
    }

    // @OperationLog(value = "登陆", operationType = "登陆")
    @PostMapping("/doLogin")
    public Result doLogin(@Validated(value = {LoginAndRegisterGroupValid.class})
                          @RequestBody LoginAndRegisterDto loginAndRegisterDto) {
        String code = getStrCode();
        log.info("code:{}", code);
        if (ObjectUtils.isEmpty(code)) {
            return Result.fail(BizCodeEnums.FAILE.getCode(), "验证码已过期！");
        }
        if (!code.equals(loginAndRegisterDto.getCode())) {
            return Result.fail(BizCodeEnums.FAILE.getCode(), "验证码不正确，请重新输入！");
        }
        Map<Object, Object> map = userService.doLogin(loginAndRegisterDto);
        if (ObjectUtils.isNotEmpty(map)) {
            return Result.ok(BizCodeEnums.SUCCESS.getCode(), "成功登录", map);
        }
        return Result.fail(BizCodeEnums.FAILE.getCode(), " 登录失败，请重新登录");
    }

    @OperationLog(value = "获取用户信息", operationType = "查询")
    @GetMapping("/getUserInfo/{userId}")
    public Result getUserInfo(@PathVariable("userId") Integer userId) {
        SysUser user = userService.getUserInfoById(userId);
        return Result.ok(user);
    }

    /**
     * 获取验证码 code
     *
     * @return 验证码
     */
    // @OperationLog(value = "获取验证码", operationType = "查询")
    @GetMapping("/doLogin")
    public Result getCode() {
        // if (redisTemplate.hasKey(RedisCodeConst.LOGIN_CODE)) {
        //     return Result.fail(BizCodeEnums.FAILE.getCode(), "验证码 5 分钟有效，请勿重复发送");
        // }
        String randomCode = RandomCode.getRandomCode(6);
        redisUtil.setValue(RedisCodeConst.LOGIN_CODE, randomCode, 1, TimeUnit.MINUTES);
        return Result.ok(randomCode);
    }

    @OperationLog(value = "检查登陆状态", operationType = "查询")
    @GetMapping("/isLogin")
    public Result isLogin() {
        if (!StpUtil.isLogin()) {
            log.error("您还没有登录！");
            return Result.fail(401, "请先登录");
        }
        // log.info("您已经登录了,当前用户 id:{}", StpUtil.getLoginId());
        return Result.ok();
    }

    @OperationLog(value = "退出登录", operationType = "修改")
    @PostMapping("/logOut")
    public Result logOut() {
        redisUtil.deleteValue(RedisCodeConst.LOGIN_CODE + StpUtil.getLoginIdAsInt());
        StpUtil.logout();
        return Result.ok();
    }

    @OperationLog(value = "查询用户信息列表", operationType = "查询")
    @GetMapping("/getUserList/{page}/{pageSize}")
    @SaCheckPermission(value = {"sys:user:manage"})
    public Result getUserList(@PathVariable("page") Integer page,
                              @PathVariable("pageSize") Integer pageSize) {
        Page<SysUser> sysUserPage = new Page<>();
        sysUserPage.setCurrent(page);
        sysUserPage.setSize(pageSize);
        Page<SysUser> pageUser = userService.page(sysUserPage);
        Map<Object, Object> map = new HashMap<>();
        if (ObjectUtils.isNotEmpty(pageUser.getRecords())) {
            map.put("records", pageUser.getRecords());
            map.put("total", pageUser.getTotal());
            return Result.ok(map);
        }
        return Result.fail(BizCodeEnums.FAILE.getCode(), "获取用户信息失败！");
    }


    @OperationLog(value = "删除用户", operationType = "删除")
    @DeleteMapping("/deleteUserById/{userId}")
    @SaCheckPermission(value = {"sys:user:del"})
    public Result deleteUserById(@PathVariable("userId") Integer userId) {
        boolean flag = StpUtil.isLogin(userId);
        boolean removeFlag = userService.removeById(userId);
        // 如果删除成功
        if (removeFlag) {
            // 如果删除的用户已经登录，则让其用户退出登录
            if (flag) {
                StpUtil.logout(userId);
            }
            return Result.ok(BizCodeEnums.SUCCESS.getCode(), "删除用户成功！");
        }
        return Result.fail(BizCodeEnums.FAILE.getCode(), "删除用户失败");
    }

    @OperationLog(value = "更新用户", operationType = "更新")
    @PutMapping("/updateUserInfo")
    @SaCheckPermission(value = {"sys:user:edit"})
    public Result updateUserInfo(@Validated(value = {UpdateGroupValid.class}) @RequestBody SysUser user) {
        if (userService.updateById(user)) {
            return Result.ok(BizCodeEnums.SUCCESS.getCode(), "用户信息修改成功！");
        }
        return Result.fail(BizCodeEnums.FAILE.getCode(), "修改用户信息失败！");
    }

    @OperationLog(value = "新增用户", operationType = "新增")
    @PostMapping("/addUserInfo")
    @SaCheckPermission(value = {"sys:user:add"})
    public Result addUserInfo(@Validated(value = {AddGroupValid.class}) @RequestBody SysUser user) {
        if (userService.saveUserInfo(user)) {
            return Result.ok(BizCodeEnums.SUCCESS.getCode(), "添加用户成功");
        }
        return Result.fail(BizCodeEnums.FAILE.getCode(), "添加用户失败");
    }

    private String getStrCode() {
        return redisUtil.getValue(RedisCodeConst.LOGIN_CODE);
    }
}
